package com.mystnihon.freeremote.manager;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Observable;

import org.apache.http.client.CookieStore;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;

import android.content.Context;
import android.util.Log;

import com.mystnihon.freeremote.FreeRemoteApplication;
import com.mystnihon.freeremote.data.GuideResultData;
import com.mystnihon.freeremote.loader.guide.CachedGuideNetworkRequest;
import com.mystnihon.freeremote.loader.guide.NetworkRequest;
import com.mystnihon.freeremote.manager.GuideNetworkManager.GuideResult.ActionType;
import com.mystnihon.freeremote.manager.GuideNetworkManager.GuideResult.ResultType;
import com.mystnihon.freeremote.util.Constants;
import com.mystnihon.freeremote.util.NetworkConnection.HttpMethod;
import com.mystnihon.freeremote.util.NetworkConnectionRequest;
import com.mystnihon.freeremote.util.NetworkConnectionResult;
import com.octo.android.robospice.SpiceManager;
import com.octo.android.robospice.persistence.exception.SpiceException;
import com.octo.android.robospice.request.listener.RequestListener;

public class GuideNetworkManager extends Observable implements Constants {

	private Context mContext;
	private BasicHttpContext mHttpContext;
	private final SpiceManager spiceManager = FreeRemoteApplication.spiceManager;

	private static final int CONNECT_LOGIN_FAILED = -1;
	private static final int CONNECT_NOT_CONNECTED = 0;
	private static final int CONNECT_CONNECTED = 1;

	private SimpleDateFormat mDateFormat = new SimpleDateFormat(WS_DATE_FORMAT, Locale.getDefault());
	private int mState = CONNECT_NOT_CONNECTED;
	private String mId = null;
	private String mIdt = null;

	public GuideNetworkManager(Context context) {
		mContext = context;

		mHttpContext = new BasicHttpContext();
		final CookieStore cookieStore = new BasicCookieStore();
		mHttpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
	}

	private void login(RequestListener<NetworkConnectionResult> listener) {
		ArrayList<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
		parameters.add(new BasicNameValuePair("login", "0223207449"));
		parameters.add(new BasicNameValuePair("pass", "jaepaequ"));
		NetworkConnectionRequest request = new NetworkConnectionRequest(mContext, LOGIN_URL, HttpMethod.Post, parameters);
		request.checkLocationChanged = true;
		spiceManager.execute(new NetworkRequest(mHttpContext, request), listener);
	}

	/**
	 * 
	 * @param forDate
	 *            the date from which you want program
	 * @param forNbHours
	 *            the time span for which you want programs in number of hours.
	 */
	public void getChannelList(final Date forDate, final int forNbHours) {
		if (mState != CONNECT_CONNECTED) {
			login(new RequestListener<NetworkConnectionResult>() {
				@Override
				public void onRequestFailure(SpiceException spiceException) {
					mState = CONNECT_LOGIN_FAILED;

				}

				@Override
				public void onRequestSuccess(NetworkConnectionResult result) {
					if (setAuthentCredentials(result)) {
						requestChannelList(forDate, forNbHours);
					}
				}
			});
		} else {
			requestChannelList(forDate, forNbHours);
		}
	}

	/**
	 * Will request program from the current hours for 2 hours
	 */
	public void getChannelForNow() {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTimeInMillis(System.currentTimeMillis());
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		getChannelList(cal.getTime(), 2);
	}

	public void getProgramForChannels(int[] channelNumber, long daystart, long duration) {

	}

	public SpiceManager getSpiceManager() {
		return spiceManager;
	}

	private void requestChannelList(Date forDate, int forNbHours) {
		if (mState == CONNECT_CONNECTED) {
			ArrayList<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();

			if (forDate != null) {
				String date = cleanParam(mDateFormat.format(forDate));
				parameters.add(new BasicNameValuePair(WS_PARAM_KEY_DATE, date));
			}

			if (forNbHours > 0 && forNbHours <= 24) {
				String duration = "";
				if (forNbHours < 10) {
					duration = cleanParam(duration.concat("0").concat(String.valueOf(forNbHours)));
				} else {
					duration = cleanParam(duration.concat(String.valueOf(forNbHours)));
				}
				parameters.add(new BasicNameValuePair(WS_PARAM_KEY_DUREE, duration));
			}

			parameters.add(new BasicNameValuePair(WS_PARAM_KEY_AJAX_GET_CHAINES, WS_PARAM_VALUE_AJAX_GET_CHAINES));
			parameters.add(new BasicNameValuePair(WS_PARAM_KEY_ID, mId));
			parameters.add(new BasicNameValuePair(WS_PARAM_KEY_IDT, mIdt));

			NetworkConnectionRequest request = new NetworkConnectionRequest(mContext, GUIDE_TV, HttpMethod.Get, parameters);
			spiceManager.execute(new CachedGuideNetworkRequest(mContext, mHttpContext, request), new RequestListener<GuideResultData>() {

				@Override
				public void onRequestFailure(SpiceException spiceException) {
					setChanged();
					notifyObservers(new GuideResult(ResultType.ERROR, ActionType.GetProgramsForNbHours, null));
				}

				@Override
				public void onRequestSuccess(GuideResultData result) {
					setChanged();
					notifyObservers(new GuideResult(ResultType.SUCCESS, ActionType.GetProgramsForNbHours, result));

				}
			});
		}
	}

	private String cleanParam(String param) {
		String date = "";
		try {
			date = URLEncoder.encode(param, Charset.defaultCharset().name());
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return date;
	}

	private boolean setAuthentCredentials(NetworkConnectionResult result) {
		Log.d("GuideManager", "" + result.newLocation);
		String idt = null;
		String id = null;

		if (result.newLocation != null) {
			String s = result.newLocation;
			String priv;
			if (s.indexOf("idt=") > -1) {
				priv = s.substring(s.indexOf("idt=") + 4);
				if (priv.indexOf("]") > -1) {
					priv = priv.substring(0, priv.indexOf(']'));
				}
				idt = priv;
				priv = s.substring(s.indexOf("?id=") + 4);
				priv = priv.substring(0, priv.indexOf('&'));
				id = priv;
			}
		}

		if (id != null && idt != null) {
			mId = id;
			mIdt = idt;
			mState = CONNECT_CONNECTED;
			return true;
		} else {
			mState = CONNECT_LOGIN_FAILED;
			return false;
		}

	}

	public static class GuideResult {
		public enum ResultType {
			SUCCESS, ERROR

		}

		public enum ActionType {
			GetProgramsForNbHours
		}

		public ResultType mSuccess;
		public Object mData;
		public ActionType mAction;

		public GuideResult(ResultType success, ActionType action, Object data) {
			mSuccess = success;
			mAction = action;
			mData = data;
		}
	}
}
